

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=dark>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/my-blog/img/fluid.png">
  <link rel="icon" href="/my-blog/img/fluid.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="木舟">
  <meta name="keywords" content="python Vue Test 测试开发 自动化测试">
  
    <meta name="description" content="前言我们知道，Vue实际上是单页面应用。 页面上的每一部分乃至整个页面的渲染，都可以通过Vue来进行控制。 但web项目，常常需要不止一个页面来进行功能模块的区分，比如：登录、用户管理、项目管理。 但由于Vue 的单页面特性，如果不借助 v-router 来进行路由管理和渲染页面，我们就很难做到 功能模块的页面区分。 安装由于我们之前的Vue是通过 npm 进行安装的，所以v-router同样可以">
<meta property="og:type" content="article">
<meta property="og:title" content="Vue路由管理">
<meta property="og:url" content="https://walker_kwu.gitee.io/my-blog/2022/12/01/notes/vue/VRouter/">
<meta property="og:site_name" content="My Blog">
<meta property="og:description" content="前言我们知道，Vue实际上是单页面应用。 页面上的每一部分乃至整个页面的渲染，都可以通过Vue来进行控制。 但web项目，常常需要不止一个页面来进行功能模块的区分，比如：登录、用户管理、项目管理。 但由于Vue 的单页面特性，如果不借助 v-router 来进行路由管理和渲染页面，我们就很难做到 功能模块的页面区分。 安装由于我们之前的Vue是通过 npm 进行安装的，所以v-router同样可以">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2022-12-01T02:55:08.000Z">
<meta property="article:modified_time" content="2023-05-23T10:37:53.259Z">
<meta property="article:author" content="木舟">
<meta property="article:tag" content="测试开发">
<meta property="article:tag" content="测试平台">
<meta property="article:tag" content="javascript">
<meta property="article:tag" content="Vue">
<meta name="twitter:card" content="summary_large_image">
  
  
    <meta name="referrer" content="no-referrer-when-downgrade">
  
  
  <title>Vue路由管理 - My Blog</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/my-blog/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/my-blog/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/my-blog/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"walker_kwu.gitee.io","root":"/my-blog/","version":"1.9.2","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"left","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/my-blog/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/my-blog/js/utils.js" ></script>
  <script  src="/my-blog/js/color-schema.js" ></script>
  


  
<meta name="generator" content="Hexo 6.2.0"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 70vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/my-blog/">
      <strong>木舟</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-blog/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-blog/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-blog/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-blog/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/my-blog/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/my-blog/img/default.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="Vue路由管理"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        木舟
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2022-12-01 10:55" pubdate>
          2022年12月1日 上午
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          11k 字
        
      </span>
    

    

    
    
      
        <span id="busuanzi_container_page_pv" style="display: none">
          <i class="iconfont icon-eye" aria-hidden="true"></i>
          <span id="busuanzi_value_page_pv"></span> 次
        </span>
        
      
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="padding-left: 2rem; margin-right: -1rem">
    <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">Vue路由管理</h1>
            
              <p class="note note-info">
                
                  
                    本文最后更新于：2023年5月23日 晚上
                  
                
              </p>
            
            
              <div class="markdown-body">
                
                <h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>我们知道，Vue实际上是单页面应用。</p>
<p>页面上的每一部分乃至整个页面的渲染，都可以通过Vue来进行控制。</p>
<p>但web项目，常常需要不止一个页面来进行功能模块的区分，比如：登录、用户管理、项目管理。</p>
<p>但由于Vue 的单页面特性，如果不借助 <strong>v-router</strong> 来进行路由管理和渲染页面，我们就很难做到 功能模块的页面区分。</p>
<h1 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h1><p>由于我们之前的Vue是通过 npm 进行安装的，所以v-router同样可以通过npm来安装。</p>
<p>进入到vue项目中，运行命令：<code>npm install vue-router@4</code></p>
<h1 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h1><p>用 Vue + Vue Router 创建单页应用非常简单。</p>
<p>通过 Vue.js，我们已经用组件组成了我们的应用。</p>
<p>当加入 Vue Router 时，我们需要做的就是将我们的组件映射到路由上，让 Vue Router 知道在哪里渲染它们。下面是一个基本的例子：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello App!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--使用 router-link 组件进行导航 --&gt;</span><br>    <span class="hljs-comment">&lt;!--通过传递 `to` 来指定链接 --&gt;</span><br>    <span class="hljs-comment">&lt;!--`&lt;router-link&gt;` 将呈现一个带有正确 `href` 属性的 `&lt;a&gt;` 标签--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/&quot;</span>&gt;</span>Go to Home<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/about&quot;</span>&gt;</span>Go to About<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br>  <span class="hljs-comment">&lt;!-- 路由出口 --&gt;</span><br>  <span class="hljs-comment">&lt;!-- 路由匹配到的组件将渲染在这里 --&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">router-view</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-view</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// 1. 定义路由组件.</span><br><span class="hljs-comment">// 也可以从其他文件导入</span><br><span class="hljs-keyword">const</span> <span class="hljs-title class_">Home</span> = &#123; <span class="hljs-attr">template</span>: <span class="hljs-string">&#x27;&lt;div&gt;Home&lt;/div&gt;&#x27;</span> &#125;<br><span class="hljs-keyword">const</span> <span class="hljs-title class_">About</span> = &#123; <span class="hljs-attr">template</span>: <span class="hljs-string">&#x27;&lt;div&gt;About&lt;/div&gt;&#x27;</span> &#125;<br><br><span class="hljs-comment">// 2. 定义一些路由</span><br><span class="hljs-comment">// 每个路由都需要映射到一个组件。</span><br><span class="hljs-keyword">const</span> routes = [<br>  &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">Home</span> &#125;,<br>  &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/about&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">About</span> &#125;,<br>]<br><br><span class="hljs-comment">// 3. 创建路由实例并传递 `routes` 配置</span><br><span class="hljs-comment">// 你可以在这里输入更多的配置，但我们在这里</span><br><span class="hljs-comment">// 暂时保持简单</span><br><span class="hljs-keyword">const</span> router = <span class="hljs-title class_">VueRouter</span>.<span class="hljs-title function_">createRouter</span>(&#123;<br>  <span class="hljs-comment">// 4. 内部提供了 history 模式的实现。为了简单起见，我们在这里使用 hash 模式。</span><br>  <span class="hljs-attr">history</span>: <span class="hljs-title class_">VueRouter</span>.<span class="hljs-title function_">createWebHashHistory</span>(),<br>  routes, <span class="hljs-comment">// `routes: routes` 的缩写</span><br>&#125;)<br><br><span class="hljs-comment">// 5. 创建并挂载根实例</span><br><span class="hljs-keyword">const</span> app = <span class="hljs-title class_">Vue</span>.<span class="hljs-title function_">createApp</span>(&#123;&#125;)<br><span class="hljs-comment">//整个应用支持路由。</span><br>app.<span class="hljs-title function_">use</span>(router)<br><br>app.<span class="hljs-title function_">mount</span>(<span class="hljs-string">&#x27;#app&#x27;</span>)<br></code></pre></td></tr></table></figure>

<p><code>router-link</code></p>
<p>通过router-link，我们会创建一个a标签，href属性值就是to属性值。</p>
<p>虽然本质上都是通过a标签进行链接条件，但是router-link会在不改变页面样式的前提下生成a标签。</p>
<p><code>router-view</code></p>
<p>router-view放在哪个位置，就代表对应跳转路由挂载的组件的渲染位置。</p>
<p>如果是 <strong>选项式api</strong>，我们可以在组件中用 <code>this.$router</code> 来访问 <code>router</code> 对象。可以通过 <code>this.$route</code> 来访问 当前路由 对象。</p>
<p><strong>当前路由</strong>对象会包含链接的各种重要参数，比如：path、params</p>
<p>如果是 <strong>组合式api</strong>，我们需要通过 <code>useRouter</code> 或 <code>useRoute</code> 函数 来获取对应的 <code>router</code> <code>route</code></p>
<h1 id="带参数的动态路由"><a href="#带参数的动态路由" class="headerlink" title="带参数的动态路由"></a>带参数的动态路由</h1><p>很多时候，我们需要将给定匹配模式的路由映射到同一个组件。</p>
<p>例如，我们可能有一个 User 组件，它应该对所有用户进行渲染，但用户 ID 不同。</p>
<p>不同的用户ID，加载不同的用户信息</p>
<p>在 Vue Router 中，我们可以在路径中使用一个动态字段来实现，我们称之为 路径参数 ：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> &#123;createRouter, createWebHashHistory&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue-router&#x27;</span><br><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">User</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;../Components/User.vue&#x27;</span><br><br><span class="hljs-keyword">const</span> routes = [<br>  <span class="hljs-comment">// 动态路由：动态字段以冒号开始</span><br>  &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/user/:id&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">User</span> &#125;,<br>]<br><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createRouter</span>(&#123;<br>  <span class="hljs-attr">history</span>: <span class="hljs-title function_">createWebHashHistory</span>(),<br>  routes, <br>&#125;)<br></code></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello App!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><br>      <span class="hljs-comment">&lt;!-- 在路径中传入参数 --&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/user/123&quot;</span>&gt;</span>Go to User123<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/user/321&quot;</span>&gt;</span>Go to User321<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-view</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-view</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>现在像 /users/123 和 /users/321 这样的 URL 都会映射到同一个路由。</p>
<p>路径参数 用冒号 : 表示。当一个路由被匹配时，它的 params 的值将在每个组件中以 this.$route.params 的形式暴露出来。</p>
<p>因此，我们可以通过更新 User 的模板来呈现当前的用户 ID：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>    &lt;div&gt;<br>        &#123;&#123;$route.params.id&#125;&#125;<br>    &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;!-- 组合式API获取动态参数 --&gt;<br>&lt;script setup&gt;<br>    import &#123; useRoute &#125; from &#x27;vue-router&#x27;;<br>    const route = useRoute()<br>    console.log(route.params.id);<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<p>你可以在同一个路由中设置有多个 路径参数，它们会映射到 $route.params 上的相应字段。例如：</p>
<table>
<thead>
<tr>
<th>匹配模式</th>
<th>匹配路径</th>
<th>$route.params</th>
</tr>
</thead>
<tbody><tr>
<td>/users/:username</td>
<td>/users/eduardo</td>
<td>{ username: ‘eduardo’ }</td>
</tr>
<tr>
<td>/users/:username/posts/:postId</td>
<td>/users/eduardo/posts/123</td>
<td>{ username: ‘eduardo’, postId: ‘123’ }</td>
</tr>
</tbody></table>
<h2 id="query"><a href="#query" class="headerlink" title="query"></a>query</h2><p>我们也可以不通过声明如 <code>/:id</code> 的方式来声明id参数</p>
<p>比如：<code>/user?id=123</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> routes = [<br>  <span class="hljs-comment">// 动态路由：动态字段以冒号开始</span><br>  &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/user&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">User</span> &#125;,<br>]<br></code></pre></td></tr></table></figure>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello App!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><br>      <span class="hljs-comment">&lt;!-- 在路径中传入参数 --&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/user?id=123&quot;</span>&gt;</span>Go to User123<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/user?id=321&quot;</span>&gt;</span>Go to User321<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-view</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-view</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>通过 <code>?</code>的方式，<code>params</code>就不能使用了，而是需要使用 <code>query</code></p>
<p>User.vue:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>    &lt;div&gt;<br>        &#123;&#123;$route.query.id&#125;&#125;<br>    &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;!-- 组合式API获取动态参数 --&gt;<br>&lt;script setup&gt;<br>    import &#123; useRoute &#125; from &#x27;vue-router&#x27;;<br>    const route = useRoute()<br>    console.log(route.query.id);<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>


<h1 id="响应路由参数的变化"><a href="#响应路由参数的变化" class="headerlink" title="响应路由参数的变化"></a>响应路由参数的变化</h1><p>使用带有参数的路由时需要注意的是，当用户从 /users/123 导航到 /users/321 时，相同的组件实例将被重复使用。</p>
<p>因为两个路由都渲染同个组件，比起销毁再创建，复用则显得更加高效。</p>
<p><strong>不过，这也意味着组件的生命周期钩子不会被调用。</strong></p>
<p>要对同一个组件中参数的变化做出响应的话，你可以简单地 watch $route 对象上的任意属性，在这个场景中，就是 $route.params ：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> <span class="hljs-title class_">User</span> = &#123;<br>  <span class="hljs-attr">template</span>: <span class="hljs-string">&#x27;...&#x27;</span>,<br>  <span class="hljs-title function_">created</span>(<span class="hljs-params"></span>) &#123;<br>    <span class="hljs-variable language_">this</span>.$watch(<br>      <span class="hljs-function">() =&gt;</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">$route</span>.<span class="hljs-property">params</span>,<br>      <span class="hljs-function">(<span class="hljs-params">toParams, previousParams</span>) =&gt;</span> &#123;<br>        <span class="hljs-comment">// 对路由变化做出响应...</span><br>      &#125;<br>    )<br>  &#125;,<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="嵌套路由"><a href="#嵌套路由" class="headerlink" title="嵌套路由"></a>嵌套路由</h1><p>一般web项目，常常会配置多层次路由来进行跳转。</p>
<p>比如：</p>
<ul>
<li>登录页面</li>
<li>系统主页面<ul>
<li>模块1</li>
<li>模块2</li>
<li>模块3</li>
</ul>
</li>
<li>系统后台<ul>
<li>模块1</li>
<li>模块2</li>
<li>模块3</li>
</ul>
</li>
</ul>
<p>这个时候，我们就需要使用 v-router 来配置 <strong>嵌套路由</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> routerHistory = <span class="hljs-title function_">createWebHistory</span>()<br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createRouter</span>(&#123;<br>  <span class="hljs-attr">history</span>: routerHistory,<br>  <span class="hljs-attr">routes</span>: [<br>    &#123;<br>      <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/loign&#x27;</span>,<br>      <span class="hljs-attr">component</span>: <span class="hljs-title class_">Login</span><br>    &#125;,<br>    &#123;<br>      <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/index/&#x27;</span>,<br>      <span class="hljs-attr">component</span>: <span class="hljs-title class_">IndexLayout</span>,  <span class="hljs-comment">// 主页布局</span><br>      <span class="hljs-attr">children</span>: [<br>        &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;homePage&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">HomePage</span> &#125;, <span class="hljs-comment">// 首页</span><br>        &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;userManage&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">UserManage</span> &#125;, <span class="hljs-comment">// 用户管理</span><br>      ]<br>    &#125;,<br>  ]<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>配置App.vue，配置第一层路由页面入口:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs Vue">&lt;template&gt;<br>    &lt;router-view&gt;&lt;/router-view&gt;<br>&lt;/template&gt;<br></code></pre></td></tr></table></figure>

<p>配置IndexLayout.vue，配置第二层路由页面入口</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs Vue">&lt;template&gt;<br>    &lt;div&gt;<br>        &lt;ul&gt;<br>            &lt;li&gt;<br>                &lt;router-link to=&quot;/indx/homePage&quot;&gt;首页&lt;/router-link&gt;<br>                &lt;router-link to=&quot;/indx/userManage&quot;&gt;用户管理&lt;/router-link&gt;<br>            &lt;/li&gt;<br>            &lt;li&gt;<br>            &lt;/li&gt;<br>        &lt;/ul&gt;<br>    &lt;/div&gt;<br>    &lt;router-view&gt;&lt;/router-view&gt;<br>&lt;/template&gt;<br></code></pre></td></tr></table></figure>

<h1 id="编程式导航"><a href="#编程式导航" class="headerlink" title="编程式导航"></a>编程式导航</h1><p>除了使用 <code>&lt;router-link&gt;</code> 创建 a 标签来定义导航链接，我们还可以借助 router 的实例方法，通过编写代码来实现。</p>
<p>想要导航到不同的 URL，可以使用 router.push 方法。</p>
<p>这个方法会向 history 栈添加一个新的记录，所以，当用户点击浏览器后退按钮时，会回到之前的 URL。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// 字符串路径</span><br>router.<span class="hljs-title function_">push</span>(<span class="hljs-string">&#x27;/users/eduardo&#x27;</span>)<br><br><span class="hljs-comment">// 带有路径的对象</span><br>router.<span class="hljs-title function_">push</span>(&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/users/eduardo&#x27;</span> &#125;)<br><br><span class="hljs-comment">// 命名的路由，并加上参数，让路由建立 url /user/:username --&gt;  /user/eduardo</span><br>router.<span class="hljs-title function_">push</span>(&#123; <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;user&#x27;</span>, <span class="hljs-attr">params</span>: &#123; <span class="hljs-attr">username</span>: <span class="hljs-string">&#x27;eduardo&#x27;</span> &#125; &#125;)<br><br><span class="hljs-comment">// 带查询参数，结果是 /register?plan=private</span><br>router.<span class="hljs-title function_">push</span>(&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/register&#x27;</span>, <span class="hljs-attr">query</span>: &#123; <span class="hljs-attr">plan</span>: <span class="hljs-string">&#x27;private&#x27;</span> &#125; &#125;)<br><br><span class="hljs-comment">// 带 hash，结果是 /about#team</span><br>router.<span class="hljs-title function_">push</span>(&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/about&#x27;</span>, <span class="hljs-attr">hash</span>: <span class="hljs-string">&#x27;#team&#x27;</span> &#125;)<br></code></pre></td></tr></table></figure>

<p>注意：如果提供了 path，params 会被忽略，上述例子中的 query 并不属于这种情况。</p>
<p>取而代之的是下面例子的做法，你需要提供路由的 name 或手写完整的带有参数的 path：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> username = <span class="hljs-string">&#x27;eduardo&#x27;</span><br><span class="hljs-comment">// 我们可以手动建立 url，但我们必须自己处理编码</span><br>router.<span class="hljs-title function_">push</span>(<span class="hljs-string">`/user/<span class="hljs-subst">$&#123;username&#125;</span>`</span>) <span class="hljs-comment">// -&gt; /user/eduardo</span><br><span class="hljs-comment">// 同样</span><br>router.<span class="hljs-title function_">push</span>(&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">`/user/<span class="hljs-subst">$&#123;username&#125;</span>`</span> &#125;) <span class="hljs-comment">// -&gt; /user/eduardo</span><br><span class="hljs-comment">// 如果可能的话，使用 `name` 和 `params` 从自动 URL 编码中获益</span><br>router.<span class="hljs-title function_">push</span>(&#123; <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;user&#x27;</span>, <span class="hljs-attr">params</span>: &#123; username &#125; &#125;) <span class="hljs-comment">// -&gt; /user/eduardo</span><br><span class="hljs-comment">// `params` 不能与 `path` 一起使用</span><br>router.<span class="hljs-title function_">push</span>(&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/user&#x27;</span>, <span class="hljs-attr">params</span>: &#123; username &#125; &#125;) <span class="hljs-comment">// -&gt; /user</span><br></code></pre></td></tr></table></figure>

<p>通过手动调用 router.push 的方法，可以让我们来决定页面哪些地方会触发跳转，而不仅仅是适用于 <strong>菜单栏</strong></p>
<p>比如：通知中心中，通知用户 “您有一条消息需要处理”</p>
<p>当用户点击这条通知后，直接跳转到对应的消息页面，进行消息处理。</p>
<h2 id="替换链接"><a href="#替换链接" class="headerlink" title="替换链接"></a>替换链接</h2><p>它的作用类似于 router.push，唯一不同的是，它在导航时不会向 history 添加新记录，正如它的名字所暗示的那样——它取代了当前的条目。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs js">router.<span class="hljs-title function_">push</span>(&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/home&#x27;</span>, <span class="hljs-attr">replace</span>: <span class="hljs-literal">true</span> &#125;)<br><span class="hljs-comment">// 相当于</span><br>router.<span class="hljs-title function_">replace</span>(&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/home&#x27;</span> &#125;)<br></code></pre></td></tr></table></figure>

<p>比如，你通过通知中心跳转后的消息页面，会自动弹出对应的消息，你可能会在跳转的 url 中加上参数 <code>msgId=1</code></p>
<p>但这也意味着，你跳转后，不手动删除msgId时，只要刷新页面，就还是会跳出弹窗。</p>
<p>所以我们可以借助 <code>router.replace</code> , 在页面加载过后，也就是 <code>onMounted</code> ，将参数msgId给替换掉，再次刷新时，就不会再跳出弹窗了。</p>
<h1 id="命名路由"><a href="#命名路由" class="headerlink" title="命名路由"></a>命名路由</h1><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> routes = [<br>  &#123;<br>    <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/user/:username&#x27;</span>,<br>    <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;user&#x27;</span>,<br>    <span class="hljs-attr">component</span>: <span class="hljs-title class_">User</span>,<br>  &#125;,<br>]<br></code></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">:to</span>=<span class="hljs-string">&quot;&#123; name: &#x27;user&#x27;, params: &#123; username: &#x27;erina&#x27; &#125;&#125;&quot;</span>&gt;</span><br>  User<br><span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs js">router.<span class="hljs-title function_">push</span>(&#123; <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;user&#x27;</span>, <span class="hljs-attr">params</span>: &#123; <span class="hljs-attr">username</span>: <span class="hljs-string">&#x27;erina&#x27;</span> &#125; &#125;)<br></code></pre></td></tr></table></figure>

<h1 id="路由组件的props"><a href="#路由组件的props" class="headerlink" title="路由组件的props"></a>路由组件的props</h1><p>在你的组件中使用 $route 会与路由紧密耦合，这限制了组件的灵活性，因为它只能用于特定的 URL。</p>
<p>虽然这不一定是件坏事，但我们可以通过 props 配置来解除这种行为：</p>
<p>我们可以将下面的代码</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> <span class="hljs-title class_">User</span> = &#123;<br>  <span class="hljs-attr">template</span>: <span class="hljs-string">&#x27;&lt;div&gt;User &#123;&#123; $route.params.id &#125;&#125;&lt;/div&gt;&#x27;</span><br>&#125;<br><span class="hljs-keyword">const</span> routes = [&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/user/:id&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">User</span> &#125;]<br></code></pre></td></tr></table></figure>

<p>替换成</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> <span class="hljs-title class_">User</span> = &#123;<br>  <span class="hljs-comment">// 请确保添加一个与路由参数完全相同的 prop 名</span><br>  <span class="hljs-attr">props</span>: [<span class="hljs-string">&#x27;id&#x27;</span>],<br>  <span class="hljs-attr">template</span>: <span class="hljs-string">&#x27;&lt;div&gt;User &#123;&#123; id &#125;&#125;&lt;/div&gt;&#x27;</span><br>&#125;<br><span class="hljs-keyword">const</span> routes = [&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/user/:id&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">User</span>, <span class="hljs-attr">props</span>: <span class="hljs-literal">true</span> &#125;]<br></code></pre></td></tr></table></figure>

<p>这允许你在任何地方使用该组件，而不仅仅是适用于v-router</p>
<p>使得该组件更容易重用和测试。</p>
<h1 id="不同的历史模式"><a href="#不同的历史模式" class="headerlink" title="不同的历史模式"></a>不同的历史模式</h1><p>在创建路由器实例时，history 配置允许我们在不同的历史模式中进行选择。</p>
<h2 id="Hash模式"><a href="#Hash模式" class="headerlink" title="Hash模式"></a>Hash模式</h2><p>hash 模式是用 createWebHashHistory() 创建的：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> &#123; createRouter, createWebHashHistory &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue-router&#x27;</span><br><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createRouter</span>(&#123;<br>  <span class="hljs-attr">history</span>: <span class="hljs-title function_">createWebHashHistory</span>(),<br>  <span class="hljs-attr">routes</span>: [<br>    <span class="hljs-comment">//...</span><br>  ],<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>它在内部传递的实际 URL 之前使用了一个哈希字符（#）。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-comment">&lt;!-- 实际页面上的url为 /index/#user --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">roter-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/index/user&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h2 id="html5模式"><a href="#html5模式" class="headerlink" title="html5模式"></a>html5模式</h2><p>用 createWebHistory() 创建 HTML5 模式，推荐使用这个模式：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> &#123; createRouter, createWebHistory &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue-router&#x27;</span><br><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createRouter</span>(&#123;<br>  <span class="hljs-attr">history</span>: <span class="hljs-title function_">createWebHistory</span>(),<br>  <span class="hljs-attr">routes</span>: [<br>    <span class="hljs-comment">//...</span><br>  ],<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>当使用这种历史模式时，URL 会看起来很 “正常”，例如 <code>https://example.com/index/user</code></p>
<h1 id="导航守卫"><a href="#导航守卫" class="headerlink" title="导航守卫"></a>导航守卫</h1><p>正如其名，vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。</p>
<p>这里有很多方式植入路由导航中：全局的，单个路由独享的，或者组件级的。</p>
<h2 id="全局前置守卫"><a href="#全局前置守卫" class="headerlink" title="全局前置守卫"></a>全局前置守卫</h2><p>使用 全局前置守卫 时，通常是需要满足以下业务场景：</p>
<ul>
<li>token校验</li>
<li>权限校验</li>
<li>获取用户配置</li>
</ul>
<p>你可以使用 router.beforeEach 注册一个全局前置守卫：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createRouter</span>(&#123; ... &#125;)<br><br>router.<span class="hljs-title function_">beforeEach</span>(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span></span>) =&gt;</span> &#123;<br>  <span class="hljs-comment">// ...</span><br>  <span class="hljs-comment">// 返回 false 以取消导航</span><br>  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span><br>&#125;)<br></code></pre></td></tr></table></figure>

<p>每个守卫方法接收两个参数：</p>
<ul>
<li>to: 即将要进入的目标 </li>
<li>from: 当前导航正要离开的路由</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs js">router.<span class="hljs-title function_">beforeEach</span>(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span></span>) =&gt;</span> &#123;<br>  <span class="hljs-keyword">if</span> (<br>    <span class="hljs-comment">// 检查用户是否已登录</span><br>    !isAuthenticated &amp;&amp;<br>    <span class="hljs-comment">// 避免无限重定向</span><br>    to.<span class="hljs-property">name</span> !== <span class="hljs-string">&#x27;Login&#x27;</span><br>  ) &#123;<br>    <span class="hljs-comment">// 将用户重定向到登录页面</span><br>    <span class="hljs-keyword">return</span> &#123; <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;Login&#x27;</span> &#125;<br>  &#125;<br>&#125;)<br></code></pre></td></tr></table></figure>

<h2 id="全局后置钩子"><a href="#全局后置钩子" class="headerlink" title="全局后置钩子"></a>全局后置钩子</h2><p>实际上，我们也许会用不到这个钩子函数。</p>
<p><strong>全局前置守卫</strong> 的应用次数是最多的。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs js">router.<span class="hljs-title function_">afterEach</span>(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span></span>) =&gt;</span> &#123;<br>  <span class="hljs-title function_">sendToAnalytics</span>(to.<span class="hljs-property">fullPath</span>)<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>不过也有应用场景：</p>
<ul>
<li>更改页面标题</li>
<li>首次登录提醒</li>
</ul>
<h2 id="独享守卫"><a href="#独享守卫" class="headerlink" title="独享守卫"></a>独享守卫</h2><p>路由独享</p>
<p>你可以直接在路由配置上定义 beforeEnter 守卫：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> routes = [<br>  &#123;<br>    <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/users/:id&#x27;</span>,<br>    <span class="hljs-attr">component</span>: <span class="hljs-title class_">UserDetails</span>,<br>    <span class="hljs-attr">beforeEnter</span>: <span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span></span>) =&gt;</span> &#123;<br>      <span class="hljs-comment">// reject the navigation</span><br>      <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span><br>    &#125;,<br>  &#125;,<br>]<br></code></pre></td></tr></table></figure>

<p>只在进入 <code>/users/:id</code> 时触发，不会在 params、query 或 hash 改变时触发。</p>
<p>例如，从 /users/2 进入到 /users/3 或者从 /users/2#info 进入到 /users/2#projects。它们只有在 从一个不同的 路由导航时，才会被触发。</p>
<h2 id="组件内守卫（组合式api）"><a href="#组件内守卫（组合式api）" class="headerlink" title="组件内守卫（组合式api）"></a>组件内守卫（组合式api）</h2><p>单独的组件中，也可以配置路由守卫</p>
<p>你可以为路由组件添加以下配置：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> &#123; onBeforeRouteLeave, onBeforeRouteUpdate &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue-router&#x27;</span><br><span class="hljs-keyword">import</span> &#123; ref &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue&#x27;</span><br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-title function_">setup</span>(<span class="hljs-params"></span>) &#123;<br>    <span class="hljs-title function_">onBeforeRouteLeave</span>(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span></span>) =&gt;</span> &#123;<br>      <span class="hljs-keyword">const</span> answer = <span class="hljs-variable language_">window</span>.<span class="hljs-title function_">confirm</span>(<br>        <span class="hljs-string">&#x27;Do you really want to leave? you have unsaved changes!&#x27;</span><br>      )<br>      <span class="hljs-comment">// 取消导航并停留在同一页面上</span><br>      <span class="hljs-keyword">if</span> (!answer) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span><br>    &#125;)<br><br>    <span class="hljs-keyword">const</span> userData = <span class="hljs-title function_">ref</span>()<br><br>    <span class="hljs-title function_">onBeforeRouteUpdate</span>(<span class="hljs-keyword">async</span> (to, <span class="hljs-keyword">from</span>) =&gt; &#123;<br>      <span class="hljs-comment">//仅当 id 更改时才获取用户，例如仅 query 或 hash 值已更改</span><br>      <span class="hljs-keyword">if</span> (to.<span class="hljs-property">params</span>.<span class="hljs-property">id</span> !== <span class="hljs-keyword">from</span>.<span class="hljs-property">params</span>.<span class="hljs-property">id</span>) &#123;<br>        userData.<span class="hljs-property">value</span> = <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetchUser</span>(to.<span class="hljs-property">params</span>.<span class="hljs-property">id</span>)<br>      &#125;<br>    &#125;)<br>  &#125;,<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="路由实践"><a href="#路由实践" class="headerlink" title="路由实践"></a>路由实践</h1><p>之前我们通过 vite 生成的项目模板</p>
<p>然后在 src 文件夹下，新建 router 文件夹</p>
<p>在其中新建 index.js</p>
<p>src/router/index.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> &#123; createRouter, createWebHistory &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue-router&#x27;</span><br><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">IndexLayout</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@root/components/IndexLayout/IndexLayout.vue&#x27;</span><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">Login</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@root/components/Login/Login.vue&#x27;</span><br><br><span class="hljs-keyword">const</span> routerHistory = <span class="hljs-title function_">createWebHistory</span>()  <span class="hljs-comment">// html5历史模式</span><br><span class="hljs-keyword">const</span> router = <span class="hljs-title function_">createRouter</span>(&#123;<br>  <span class="hljs-attr">history</span>: routerHistory,<br>  <span class="hljs-attr">routes</span>: [<br>    &#123;<br>      <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/login&#x27;</span>,<br>      <span class="hljs-attr">component</span>: <span class="hljs-title class_">Login</span><br>    &#125;,<br>    &#123;<br>      <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/index/&#x27;</span>,<br>      <span class="hljs-attr">component</span>: <span class="hljs-title class_">IndexLayout</span>,<br>      <span class="hljs-attr">children</span>: [<br>        &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;homePage&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">HomePage</span> &#125;,<br>        &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;userManage&#x27;</span>, <span class="hljs-attr">component</span>: <span class="hljs-title class_">UserManage</span> &#125;,<br>      ]<br>    &#125;,<br>  ]<br>&#125;)<br><br>router.<span class="hljs-title function_">beforeEach</span>(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span></span>)=&gt;</span>&#123;<br>    <span class="hljs-comment">// 用户配置获取</span><br>    <span class="hljs-comment">// token校验</span><br>    <span class="hljs-comment">// 权限校验</span><br>&#125;)<br><br><span class="hljs-comment">// 最后将router实例导出</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> router<br></code></pre></td></tr></table></figure>

<p>组件入口文件，src/main.js:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> &#123; createApp &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue&#x27;</span><br><span class="hljs-keyword">import</span> <span class="hljs-title class_">App</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./App.vue&#x27;</span><br><span class="hljs-keyword">import</span> myrouter  <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./router/index.js&#x27;</span><br><br><span class="hljs-keyword">const</span> app = <span class="hljs-title function_">createApp</span>(<span class="hljs-title class_">App</span>)<br>app.<span class="hljs-title function_">use</span>(myrouter)<br>app.<span class="hljs-title function_">mount</span>(<span class="hljs-string">&#x27;#app&#x27;</span>)<br></code></pre></td></tr></table></figure>

<p>主组件 App.vue:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs Vue">&lt;template&gt;<br>    &lt;router-view /&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>import locale from &#x27;ant-design-vue/lib/locale-provider/zh_CN&#x27;;<br> <br>export default &#123;<br>  name: &#x27;App&#x27;,<br>  setup() &#123;<br>  &#125;,<br>&#125;;<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<p>剩下的就是编写 Login组件 以及 IndexLayout组件</p>
<p>其中，在 IndexLayout组件 中定义好二级路由显示区域即可。</p>

                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/my-blog/categories/%E6%B5%8B%E8%AF%95%E5%BC%80%E5%8F%91/" class="category-chain-item">测试开发</a>
  
  
    <span>></span>
    
  <a href="/my-blog/categories/%E6%B5%8B%E8%AF%95%E5%BC%80%E5%8F%91/Vue/" class="category-chain-item">Vue</a>
  
  

  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/my-blog/tags/%E6%B5%8B%E8%AF%95%E5%BC%80%E5%8F%91/">#测试开发</a>
      
        <a href="/my-blog/tags/%E6%B5%8B%E8%AF%95%E5%B9%B3%E5%8F%B0/">#测试平台</a>
      
        <a href="/my-blog/tags/javascript/">#javascript</a>
      
        <a href="/my-blog/tags/Vue/">#Vue</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>Vue路由管理</div>
      <div>https://walker_kwu.gitee.io/my-blog/2022/12/01/notes/vue/VRouter/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>木舟</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2022年12月1日</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>更新于</div>
          <div>2023年5月23日</div>
        </div>
      
      <div class="license-meta-item">
        <div>许可协议</div>
        <div>
          
            
            
              <a target="_blank" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
              <span class="hint--top hint--rounded" aria-label="BY - 署名">
                <i class="iconfont icon-by"></i>
              </span>
              </a>
            
              <a target="_blank" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
              <span class="hint--top hint--rounded" aria-label="NC - 非商业性使用">
                <i class="iconfont icon-nc"></i>
              </span>
              </a>
            
              <a target="_blank" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
              <span class="hint--top hint--rounded" aria-label="SA - 相同方式共享">
                <i class="iconfont icon-sa"></i>
              </span>
              </a>
            
          
        </div>
      </div>
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/my-blog/2022/12/01/notes/vue/Vuex/" title="Vuex全局状态管理">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">Vuex全局状态管理</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/my-blog/2022/11/20/notes/vue/defineExpose/" title="Vue父子通信2">
                        <span class="hidden-mobile">Vue父子通信2</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <span>By 木舟</span> <i class="iconfont icon-love"></i> 
    </div>
  
  
    <div class="statistics">
  
  

  
    
      <span id="busuanzi_container_site_pv" style="display: none">
        总访问量 
        <span id="busuanzi_value_site_pv"></span>
         次
      </span>
    
    
      <span id="busuanzi_container_site_uv" style="display: none">
        总访客数 
        <span id="busuanzi_value_site_uv"></span>
         人
      </span>
    
    
  
</div>

  
  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/my-blog/js/events.js" ></script>
<script  src="/my-blog/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/my-blog/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      headingSelector : CONFIG.toc.headingSelector || 'h1,h2,h3,h4,h5,h6',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      collapseDepth   : CONFIG.toc.collapseDepth || 0,
      scrollSmooth    : true,
      headingsOffset  : -boardTop
    });
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.10/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/my-blog/js/local-search.js" ></script>

  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/my-blog/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
